<template lang="html">
  <img alt="Favicon"
    height="16"
    width="16"
    ref="image"
    :src="iconUrl"
    :class="classes"
    @load="onLoaded"
    @error="onError"/>
</template>

<script>

import * as Vibrant from 'node-vibrant';

const getColors = function(image) {
  const vib = new Vibrant(image);
  return new Promise(function(resolve, reject) {
    vib.getPalette(function(err, pal) {
      if (err) { reject(err); return; }
      resolve(pal);
    });
  });
};

// Yellow star
const fallbackColor = '#FDD835';
const fallbackUrl = '';

export default {
  props: {
    url: {
      type: String,
      default: ''
    },
    classes: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      iconUrl: this.url,
      fetchedValidIcon: false
    };
  },
  methods: {
    onError() {
      this.iconUrl = fallbackUrl;
      this.onLoaded();
    },
    async onLoaded() {
      const needsColorExtraction = this.iconUrl !== fallbackUrl && this.isValid();
      const color = needsColorExtraction ? await this.selectPaletteColor() : fallbackColor;
      this.fetchedValidIcon = color !== undefined;
      this.emitColor(this.fetchedValidIcon ? color : fallbackColor);
    },
    async selectPaletteColor() {
      const palettes = await getColors(this.$refs.image);
      return (palettes.Muted ||
              palettes.Vibrant ||
              palettes.LightVibrant ||
              palettes.LightMuted ||
              palettes.DarkMuted ||
              palettes.DarkVibrant).getHex();
    },
    emitColor(color) {
      this.$emit('gotColor', color);
    },
    isValid() {
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      const img = this.$refs.image;
      if (img !== undefined) {
        ctx.drawImage(img, 0, 0);
        // valid non-empty icons have some pixel values > 0
        return ctx.getImageData(0, 0, 16, 16).data.some(val => val > 0);
      } else {
        return false;
      }
    }
  },
  mounted() {
    if (this.iconUrl === fallbackUrl) {
      this.iconUrl = this.url;
    }
  }
};
</script>
